package com.gzmu.myprint.controller;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gzmu.myprint.mapper.PayMentMapper;
import com.gzmu.myprint.mapper.PrintUserMapper;
import com.gzmu.myprint.model.PayInfo;
import com.gzmu.myprint.model.PayMent;
import com.gzmu.myprint.model.PrintUser;
import com.gzmu.myprint.model.User;
import com.gzmu.myprint.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.gzmu.myprint.constant.Constant.*;
import static com.gzmu.myprint.vo.CommonUtil.getOpenid;
import static com.gzmu.myprint.vo.CommonUtil.getVerification;

@Controller
public class PayController {
    @Autowired
    private PrintUserMapper userMapper;

    @Autowired
    private PayMentMapper payMentMapper;

    @ResponseBody
    @RequestMapping(value = "/loadUser", produces = "text/html;charset=UTF-8")
    public String loadUser(int uid){
        String content = null;
        Map map = new HashMap();
        ObjectMapper mapper = new ObjectMapper();
        PrintUser user = userMapper.findUserByUid(uid);
        if (user == null)
            user = new PrintUser();
        try {
            map.put("user", user);
            content = mapper.writeValueAsString(map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content;
    }

    @ResponseBody
    @RequestMapping(value = "/userInfoUpdate", produces = "text/html;charset=UTF-8")
    public String userInfoUpdate(HttpServletRequest request){
        String content = null;
        Map map = new HashMap();
        ObjectMapper mapper = new ObjectMapper();
        String openid = request.getParameter("openid");
        String avatarUrl = request.getParameter("avatarUrl");
        String nickName = request.getParameter("nickName");
        String gender = request.getParameter("gender");
        String name = request.getParameter("name");
        String phone = request.getParameter("phone");
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        PrintUser user = new PrintUser();
        user.setOpenid(openid);
        user.setAvatarUrl(avatarUrl);
        user.setNickName(nickName);
        user.setGender(gender);
        user.setPhone(phone);
        user.setName(name);
        user.setTime(df.format(new Date()));
        System.out.println("+++user: " + user.toString());
        int res = userMapper.InsertOrUpUser(user);
        try {
            map.put("res",res);
            content = mapper.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return content;
    }

    @ResponseBody
    @RequestMapping(value = "/notify", produces = "text/html;charset=UTF-8")
    public String notify(HttpServletRequest request){
        String content = null;
        Map map = new HashMap();
        ObjectMapper mapper = new ObjectMapper();
        String uid = request.getParameter("uid");
        String money = request.getParameter("money");
        String moneyX = request.getParameter("moneyX");
        String nonceStr = request.getParameter("nonceStr");

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        PayMent payMent = new PayMent();
        payMent.setTime(df.format(date));
        payMent.setUid(Integer.valueOf(uid));
        payMent.setMoney(Float.valueOf(money));
        payMent.setNonceStr(nonceStr);
        payMent.setState(1);
        payMent.setOrders(MCH_ID + date.getTime());
        int res = payMentMapper.InsertOrUpPayMent(payMent);
        PrintUser user = userMapper.findUserByUid(Integer.valueOf(uid));
        float newMoney = user.getMoney() + Float.valueOf(money) + Float.valueOf(moneyX);
        System.out.println("+++user: " + uid + " money:" + newMoney);
        res *= userMapper.upDateUserOfPrice(Integer.valueOf(uid), newMoney);

        try {
            map.put("res",res);
            content = mapper.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return content;
    }

    @ResponseBody
    @RequestMapping(value = "/bindingPhone", produces = "text/html;charset=UTF-8")
    public String bindingPhone(HttpServletRequest request){
        String content = null;
        Map map = new HashMap();
        ObjectMapper mapper = new ObjectMapper();
        String mode = request.getParameter("mode");
        String mobile = request.getParameter("mobile");
        String uid = request.getParameter("uid");
        PrintUser user = new PrintUser();
        String scode;
        if (mode.equals("send")){
            scode = getVerification(mobile);
        }else{
            user.setPhone(mobile);
            user.setId(Integer.valueOf(uid));
            scode = userMapper.InsertOrUpUser(user) + "";
        }
        try {
            map.put("scode",scode);
            content = mapper.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return content;
    }

    @ResponseBody
    @RequestMapping(value = "/onGetOpenid", produces = "text/html;charset=UTF-8")
    public String onGetOpenid(String code){
        System.out.println("+++code: " + code);
        String content = null;
        Map map = new HashMap();
        ObjectMapper mapper = new ObjectMapper();

        PrintUser user = new PrintUser();
        String openId = getOpenid(code,APP_ID,APP_SECRET);
        if(!StringUtils.isBlank(openId)){
            openId = openId.replace("\"", "").trim();
            user = userMapper.findUerByOpenId(openId);
            if (user == null){
                user = new PrintUser();
                user.setOpenid(openId);
                userMapper.InsertOrUpUser(user);
                user.setId(userMapper.getLastUid());
            }
        }

        try {
            map.put("uid", user.getId());
            map.put("openid", user.getOpenid());
            content = mapper.writeValueAsString(map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content;
    }

    @ResponseBody
    @RequestMapping(value = "/prePay", produces = "text/html;charset=UTF-8")
    public String prePay(HttpServletRequest request) {
        String content = null;
        Map map = new HashMap();
        ObjectMapper mapper = new ObjectMapper();
        String openid = request.getParameter("openid");
        String money = request.getParameter("money");
        String clientIP = CommonUtil.getClientIp(request);

        System.out.println("+++openid: " + openid + " money:" + money);
        String randomNonceStr = RandomUtils.generateMixString(32);
        double moneyd = Double.valueOf(money) * 100;
        String prepayId = unifiedOrder(openid, clientIP, randomNonceStr, (int)moneyd);

        System.out.println("+++prepayId: " + prepayId);
        if(StringUtils.isBlank(prepayId)) {
            prepayId = "-1";
        }

        try {
            map.put("prepayId", "prepay_id=" + prepayId);
            map.put("nonceStr", randomNonceStr);
            map.put("appId", APP_ID);
            map.put("key", PAY_KEY);
            map.put("signType", "MD5");
            content = mapper.writeValueAsString(map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content;
    }
    /**
     * 调用统一下单接口
     * @param openId
     */
    private String unifiedOrder(String openId, String clientIP, String randomNonceStr, int total) {
        try {
            String url = URL_UNIFIED_ORDER;
            PayInfo payInfo = createPayInfo(openId, clientIP, randomNonceStr, total);
            String md5 = getSign(payInfo);
            payInfo.setSign(md5);

            System.out.println("+++md5 value: " + md5);
            String xml = CommonUtil.payInfoToXML(payInfo);
            xml = xml.replace("__", "_").replace("<![CDATA[1]]>", "1");
            //xml = xml.replace("__", "_").replace("<![CDATA[", "").replace("]]>", "");
            System.out.println(xml);

            StringBuffer buffer = HttpUtil.httpsRequest(url, "POST", xml);
            System.out.println("unifiedOrder request return body: \n" + buffer.toString());
            Map<String, String> result = CommonUtil.parseXml(buffer.toString());

            String return_code = result.get("return_code");
            if(StringUtils.isNotBlank(return_code) && return_code.equals("SUCCESS")) {
                String return_msg = result.get("return_msg");
                if(StringUtils.isNotBlank(return_msg) && !return_msg.equals("OK")) {
                    System.out.println("unifiedOrder error");
                    return null;
                }
                String prepay_Id = result.get("prepay_id");
                return prepay_Id;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private PayInfo createPayInfo(String openId, String clientIP, String randomNonceStr, int total) {
        Date date = new Date();
        String timeStart = TimeUtils.getFormatTime(date, TIME_FORMAT);
        String timeExpire = TimeUtils.getFormatTime(TimeUtils.addDay(date, TIME_EXPIRE), TIME_FORMAT);
        String randomOrderId = CommonUtil.getRandomOrderId();

        PayInfo payInfo = new PayInfo();
        payInfo.setAppid(APP_ID);
        payInfo.setMch_id(MCH_ID);
        payInfo.setDevice_info("WEB");
        payInfo.setNonce_str(randomNonceStr);
        payInfo.setSign_type("MD5");  //默认即为MD5
        payInfo.setBody("word");
        payInfo.setAttach("print");
        payInfo.setOut_trade_no(randomOrderId);
        payInfo.setTotal_fee(total);
        payInfo.setSpbill_create_ip(clientIP);
        payInfo.setTime_start(timeStart);
        payInfo.setTime_expire(timeExpire);
        payInfo.setNotify_url(URL_NOTIFY);
        payInfo.setTrade_type("JSAPI");
        payInfo.setLimit_pay("no_credit");
        payInfo.setOpenid(openId);
        return payInfo;
    }

    private String getSign(PayInfo payInfo) throws Exception {
        StringBuffer sb = new StringBuffer();
        sb.append("appid=" + payInfo.getAppid())
                .append("&attach=" + payInfo.getAttach())
                .append("&body=" + payInfo.getBody())
                .append("&device_info=" + payInfo.getDevice_info())
                .append("&limit_pay=" + payInfo.getLimit_pay())
                .append("&mch_id=" + payInfo.getMch_id())
                .append("&nonce_str=" + payInfo.getNonce_str())
                .append("&notify_url=" + payInfo.getNotify_url())
                .append("&openid=" + payInfo.getOpenid())
                .append("&out_trade_no=" + payInfo.getOut_trade_no())
                .append("&sign_type=" + payInfo.getSign_type())
                .append("&spbill_create_ip=" + payInfo.getSpbill_create_ip())
                .append("&time_expire=" + payInfo.getTime_expire())
                .append("&time_start=" + payInfo.getTime_start())
                .append("&total_fee=" + payInfo.getTotal_fee())
                .append("&trade_type=" + payInfo.getTrade_type())
                .append("&key=" + PAY_KEY);
        System.out.println("排序后的拼接参数：" + sb.toString());
        return CommonUtil.getMD5(sb.toString().trim()).toUpperCase();
    }
}
